/*
 * Systemprogrammierung
 * Multiplayer-Quiz
 *
 * Server
 * 
 * user.c: Implementierung der User-Verwaltung
 */

#include "common/rfc.h"
#include "user.h"
#include "login.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <pthread.h>
#include "catalog.h"

PLAYER spieler[4];

pthread_mutex_t user_mutex;
/*
 * Initialisiert das Array der User
 */
void init() {
	for (int i = 0; i < 4; i++) {
		spieler[i].id = -1;
		spieler[i].name[0] = '\0';
	}
}

/*
 * Fuegt Spieler zur UserListe hinzu
 *
 * char* name Name des Spielers
 * int length Laenge des Namen
 * int sock Socket des Clients mit diesem Namen
 *
 * return id ID des Users oder falscher Name(-1) oder zu viel User (4)
 */
int addPlayer(char *name, int length, int sock) {
	name[length] = 0;
	int ids[4] = { 0 };
	for (int i = 0; i < 4; i++) {
		// Auf gleichen Namen pruefen
		if (strncmp(spieler[i].name, name, length + 1) == 0) {
			return -1;
		}
		// Belegte Plaetze erkennen
		if (spieler[i].id != -1) {
			ids[spieler[i].id] = 1;
		}
	}
	// Naechsten leeren Platz suchen
	for (int i = 0; i < 4; i++) {
		if (ids[i] == 0) {
			for (int c = 0; c < 4; c++) {
				if (ids[c] == 0) {
					spieler[c].id = i;
					strncpy(spieler[c].name, name, length + 1);
					spieler[c].sockDesc = sock;
					return i;
				}
			}
		}
	}
	return 4;
}

int removePlayer(int id) {
	spieler[id].id = -1;
	spieler[id].name[0] = '\0';
	spieler[id].sockDesc = 0;
	return 0;
}

/*
 * sendet PlayerList an alle User
 *
 */
void sendPlayerList() {
	PACKET player;
	player.header.type = RFC_PLAYERLIST;
	int users = 0;
// Spielerliste in PLAYERLIST schreiben
	for (int i = 0; i < 4; i++) {
// Wenn Spieler vorhanden sind
		if (spieler[i].id != -1 && spieler[i].sockDesc != 0) {
			PLAYERLIST p;
			p.id = spieler[i].id;
			strncpy(p.playername, spieler[i].name, 32);
			p.score = 0;
			player.content.playerlist[users] = p;
			users++;
		}
	}
// Laenge der Message: Anzahl der Spieler * 37 (Groeße der PLAYERLIST)
	player.header.length = htons(sizeof(PLAYERLIST) * users);
// An alle Clients senden
	for (int c = 0; c < 4; c++) {
		if (spieler[c].sockDesc != 0) {
			// Packet senden
			packetSchreiben(player, spieler[c].sockDesc);
		}
	}
}
/*
 * Gibt Player zurück
 *
 * param id UserID
 * return PLAYER Spielerstruktur
 */
PLAYER getUser(int client_id) {
	for (int i = 0; i < 4; i++) {
		if (spieler[i].id == client_id) {
			return spieler[i];
		}
	}
	PLAYER error;
	error.id = -1;
	error.name[0] = "0";
	error.sockDesc = -1;
	return error;
}

void SendCatalogChange() {
	PACKET packet;
	packet = getActiveCatalog();
	for (int i = 1; i < 4; i++) {
		if (spieler[i].id != -1 && spieler[i].sockDesc != 0) {
			packetSchreiben(packet, spieler[i].sockDesc);
		}
	}
	return;
}

void SendToAll(PACKET pack) {
	for (int i = 0; i < 4; i++) {
		if (spieler[i].id != -1 && spieler[i].sockDesc != 0) {
			packetSchreiben(pack, spieler[i].sockDesc);
		}
	}
	return;
}

int UserCount(){
	int user = 0;
	for (int i = 0; i < 4; i++) {
// Wenn Spieler vorhanden sind
		if (spieler[i].id != -1) {
			user++;
		}
	}
	return user;
}

/** Initialisiert Mutex der Userdaten
 *
 */

int create_user_mutex() {
	if (pthread_mutex_init(&user_mutex, NULL) != 0) {
		perror("Mutex-Fehler: ");
		return -1;
	}
	return 0;
}

/**
 * Sperrt Zugriff auf Userdaten
 *
 */

void user_mutex_lock() {
	pthread_mutex_lock(&user_mutex);
}

/** Gewährt Zugriff auf Userdaten
 *
 */

void user_mutex_unlock() {
	pthread_mutex_unlock(&user_mutex);
}

